/**
 * @file macro_overload.h
 * @author Linquan  
 * @brief  宏重载
 * @version 1.0
 * @date 2024-06-07
 * 
 * @copyright Copyright (c) 2024
 * @note
 * 
 *      包含8种宏函数：
 *      1、计算传入宏的参数个数（最大支持计算15个以内参数数量）
 *      2、参数连接宏（最大支持9个参数连接）
 *      3、单一函数设置默认输入参数
 *      4、函数重载
 *      5、using 使用
 *      6、foreach 遍历数组元素
 *      7、reverse_foreach 逆向遍历数组元素
 *      8、ptr_foreach 使用指针，遍历后 number个元素的值
 *      9、MIN，MAX 比较两个数据大小
 *      10、with()局部指针声明工具
 * 
 * history:
 *         20240619:添加 reverse_foreach，ptr_foreach，MIN MAX，with(),四种宏函数
 */

#ifndef MACRO_OVERLOAD_H
#define MACRO_OVERLOAD_H



/**
 *  1、计算传入宏的参数个数
 *  最大可计算15个参数以内的数量，”...“保证传入的参数长度可以随意
 *  API：VA_ARGS_COUNT(传入的参数__VA_ARGS__)
 *  example：VA_ARGS_COUNT(a,c,e,d)  -----> 输出4,4个参数
 *  
 */
#ifndef VA_ARGS_COUNT_IMPL
#define VA_ARGS_COUNT_IMPL( _0, _1,_2,_3,_4,_5,_6,_7,_8,_9, _10,_11,\
                            _12,_13,_14,_15, _16, N,...)   N  
#endif

#ifndef VA_ARGS_COUNT
#define VA_ARGS_COUNT(...)  VA_ARGS_COUNT_IMPL(dummy, ##__VA_ARGS__ ,\
                            16,15,14,13,12,11,10,9,8, 7,6, 5,4,3, 2, 1, 0)
#endif

/**
 * 2、参数连接宏
 * 最大支持9个参数连接
 * API：CONNECT_N(...) 
 *      HEX_VALUE(...) 用于组成一个十六进制数字，只能传入十六进制的数字
 * example： CONNECT_N(func_,name_,is_,connect) ---> 组成名称：func_name_is_connect
 *           HEX_VALUE(A,B,3,2) ---> 0xAB32     ---> 十六进制 0XAB32
*/

#undef __CONNECT2
#undef __CONNECT3
#undef __CONNECT4
#undef __CONNECT5
#undef __CONNECT6
#undef __CONNECT7
#undef __CONNECT8
#undef __CONNECT9

#undef CONNECT2
#undef CONNECT3
#undef CONNECT4
#undef CONNECT5
#undef CONNECT6
#undef CONNECT7
#undef CONNECT8
#undef CONNECT9

#undef CONNECT

#define __CONCAT_BETWEEN(A,B)  A##B

#define __CONNECT2(__0, __1)           \
        __0##__1
#define __CONNECT3(__0, __1, __2)      \
        __0##__1##__2
#define __CONNECT4(__0, __1, __2, __3) \
        __0##__1##__2##__3
#define __CONNECT5(__0, __1, __2, __3,__4)  \
        __0##__1##__2##__3##__4
#define __CONNECT6(__0, __1, __2, __3,__4,__5)  \
        __0##__1##__2##__3##__4##__5
#define __CONNECT7(__0, __1, __2, __3,__4,__5,__6)  \
        __0##__1##__2##__3##__4##__5##__6
#define __CONNECT8(__0, __1, __2, __3, __4, __5,__6,__7)      \
           __0##__1##__2##__3##__4##__5##__6##__7
#define __CONNECT9(__0, __1, __2, __3, __4, __5, __6,__7,__8) \
           __0##__1##__2##__3##__4##__5##__6##__7##__8

/* 安全套 */

#define CONCAT(A,B) __CONCAT_BETWEEN(A,B)

#define CONNECT2(__0, __1)                  \
    __CONNECT2(__0, __1)        
#define CONNECT3(__0, __1, __2)             \
    __CONNECT3(__0, __1, __2)       
#define CONNECT4(__0, __1, __2, __3)        \
    __CONNECT4(__0, __1, __2, __3)
#define CONNECT5(__0, __1, __2, __3,__4)    \
     __CONNECT5(__0, __1, __2, __3,__4)
#define CONNECT6(__0, __1, __2, __3, __4, __5)        \
    __CONNECT6(__0, __1, __2, __3, __4, __5)
#define CONNECT7(__0, __1, __2, __3, __4, __5, __6)        \
    __CONNECT7(__0, __1, __2, __3, __4, __5, __6)
#define CONNECT8(__0, __1, __2, __3, __4, __5, __6, __7)        \
    __CONNECT8(__0, __1, __2, __3, __4, __5, __6, __7)
#define CONNECT9(__0, __1, __2, __3, __4, __5, __6, __7, __8)   \
    __CONNECT9(__0, __1, __2, __3, __4, __5, __6, __7, __8)

/* 最终的宏 */
#define CONNECT_N(...)    CONCAT(CONNECT,VA_ARGS_COUNT(__VA_ARGS__))(__VA_ARGS__)


/* 组十六进制数据*/
#define HEX_VALUE(...)    CONNECT_N(0X,__VA_ARGS__)


/**
 * 3. Specify the default parameters for a single function input.
 * API: FUNC_MUTI_ARG (function name, input parameter)
 * method：
 *  1.  Define the default parameter macro
 *  2.  Define a macro with default parameters for the single function,
 *          Macro name format: function name + number of input parameters 
 *          Macro Content: The default input parameter for this single function
 *  3. When calling a function, call macro :
 *       FUNC_MUTI_ARG (function name, input parameter ) 
 * 
 * 
 * 3、单一函数输入指定默认参数，
 * API： FUNC_MUTI_ARG（函数名，函数需要输入的参数）
 * method：
 *      1、定义默认参数宏
 *      2、为该单一函数 定义带有默认参数的宏,
 *          该宏名格式： 函数名+输入参数的个数 
 *          宏内容：该单一函数的默认输入参数
 *      3、调用函数的时候，使用FUNC_MUTI_ARG（函数名，函数需要外界输入的参数）宏进行调用
 *      
 */
#define EXPAND(x,y)                CONNECT2(x,y)

/* 宏来处理函数调用，基于参数数量选择具体实现 */
#define FUNC_CHOOSER_IMPL(name,count, ...)   EXPAND(name, count)(__VA_ARGS__  )
#define FUNC_CHOOSER(name,...)               FUNC_CHOOSER_IMPL(name, VA_ARGS_COUNT(__VA_ARGS__), __VA_ARGS__ )

// 最终的宏：
#define FUNC_MUTI_ARG(func_name,...)       FUNC_CHOOSER( func_name, __VA_ARGS__ )

/**
 * 4、函数重载
 *  针对不同参数数量，选择不同的函数进行调用
 * method：
 *      1、为某种功能，定义多个含有不同参数数量的函数
 *          使用 RELOAD_FUC_NAME(func_name,arg_num) 宏进行函数定义
 *          其中：func_name 是 想要定义的函数名，arg_num是 该函数需要传入参数数量
 *          
 */
#define FUNC_RELOAD(func_name, ...)                               \
        CONNECT2(func_name,VA_ARGS_COUNT(__VA_ARGS__)) \
        (__VA_ARGS__)

#define RELOAD_FUC_NAME(func_name,arg_num)   CONNECT2(func_name,arg_num)



/**
 * 5、 using 使用
 *      在代码进入using结构中，可以提前执行某些操作
 *      随后 执行结构内需要执行的内容
 *      执行结束后，进行扫尾工作，扫尾工作是事先定义好的
 * metioh：
 *      using(...)
 *      根据传参个数不同，具有三种重载格式：
 *          1、using(声明)
 *          2、using(声明，退出后的扫尾工作)
 *          3、using(声明，进入前准备工作， 退出后的扫尾工作),
 *             该格式 “退出扫尾工作“部分可以不填，可以只有前期准备工作
 */

/* 仅  参数声明，无进入退出的执行 */


#undef __using1
#undef __using2
#undef __using3
#undef __using4
#undef using

#define __using1(__declare, ...)                                                    \
            for (__declare,##__VA_ARGS__, *(CONNECT_N(__using__, __LINE__, _ptr)) = NULL;    \
                 (CONNECT_N(__using__, __LINE__, _ptr))++ == NULL;             \
                )

/* 带有单一声明，退出时执行*/
#define __using2( __declare, __on_leave_expr)                                  \
            for (__declare, *(CONNECT_N(__using__, __LINE__, _ptr)) = NULL;    \
                 (CONNECT_N(__using__, __LINE__, _ptr))++ == NULL;             \
                 (__on_leave_expr)                                               \
            )

/* 带有参数声明，及进入、退出时执行 ，退出部分可以不填，只保留前期准备工作 */
#define __using3(__declare, __on_enter_expr, __on_leave_expr)                  \
            for (__declare, *CONNECT_N(__using_, __LINE__,_ptr) = NULL;        \
                 CONNECT_N(__using_, __LINE__,_ptr)++ == NULL ?                \
                    ((__on_enter_expr),1) : 0;                                 \
                 (__on_leave_expr )                                              \
                )
/* 带有两个声明参数，用于 foreach*/
#define __using4(__dcl_type, __dcl_item, __on_enter_expr, __on_leave_expr)              \
            for (__dcl_type, __dcl_item, *CONNECT3(__using_, __LINE__,_ptr) = NULL;     \
                 CONNECT3(__using_, __LINE__,_ptr)++ == NULL ?                  \
                    ((__on_enter_expr),1) : 0;                                  \
                 (__on_leave_expr )                                               \
                )

/* 最终宏 */
#define using(...)  \
            CONNECT2(__using, VA_ARGS_COUNT(__VA_ARGS__))(__VA_ARGS__)




/**
 * 6、foreach 遍历数组元素
 *   method：
 *          1、两个参数：foreach(数组类型，数组名)
 *              使用指针：“_” 指向遍历内容
 *          2、三个参数：foreach(数组类型，数组名，读取的指针ptr)
 *              ptr无需提前定义
 */

#undef _

#undef  foreach2
#undef  foreach3
#undef  foreach


#define SAFE_NAME(__NAME)   CONNECT3(__,__NAME,__LINE__)

#ifndef dimof
#   define dimof(__array)          (sizeof(__array)/sizeof(__array[0]))
#endif

#define foreach2(__type, __array)                                               \
            using(__type *_ = __array)                                          \
            for (   uint_fast32_t SAFE_NAME(count) = dimof(__array);            \
                    SAFE_NAME(count) > 0;                                       \
                    _++, SAFE_NAME(count)--                                     \
                )


/* using 中 在 _p = _p 后一个 “,”，第四个参数为可空，所以 一共四个参数 */
#define foreach3(__type, __array, __item)                                       \
            using(__type *_p = __array, *__item = _p, _p = _p , _p = _p)                \
            for (   uint_fast32_t SAFE_NAME(count) = dimof(__array);    \
                    SAFE_NAME(count) > 0;                               \
                    _p++, __item = _p, SAFE_NAME(count)--               \
                )


#define foreach(...)                                                            \
            CONNECT2(foreach, VA_ARGS_COUNT(__VA_ARGS__))(__VA_ARGS__)



/**
 * 7、reverse_foreach 遍历数组元素
 *   method：
 *          1、两个参数：reverse_foreach(数组类型，数组名)
 *              使用指针：“_” 指向遍历内容
 *          2、三个参数：reverse_foreach(数组类型，数组名，读取的指针ptr)
 *              ptr无需提前定义
 */

#undef reverse_foreach2
#undef reverse_foreach3
#undef reverse_foreach

#define reverse_foreach2(__type, __array)                                               \
            using(__type *_ = (__array+dimof(__array)-1))                                          \
            for (   uint_fast32_t SAFE_NAME(count) = dimof(__array);            \
                    SAFE_NAME(count) > 0;                                       \
                    _--, SAFE_NAME(count)--                                     \
                )

#define reverse_foreach3(__type, __array, __item)                                       \
            using(__type *_p = (__array+dimof(__array)-1), *__item = _p, _p = _p ,_p = _p)                \
            for (   uint_fast32_t SAFE_NAME(count) = dimof(__array);    \
                    SAFE_NAME(count) > 0;                               \
                    _p--, __item = _p, SAFE_NAME(count)--               \
                )
/* 最终宏 */
#define reverse_foreach(...)                                                            \
            CONNECT2(reverse_foreach, VA_ARGS_COUNT(__VA_ARGS__))(__VA_ARGS__)


/**
 * 8、ptr_foreach 用指针遍历后number个值
 *   method：
 *   两个参数，ptr的值会在遍历中改变：foreach(  指向开始地址的指针ptr(需预先定义），遍历个数) 
 *   或   
 *   三个参数，ptr的值不会在遍历中改变：foreach(  数组类型， 指向开始地址的指针ptr(需预先定义）， 遍历个数)
 */
#undef ptr_foreach2
#undef ptr_foreach3
#undef ptr_foreach

/* 指针遍历 */
/* 使用一个指向开始地址的指针，移动该指针遍历num个数据，改变 _ptr的值*/
#define ptr_foreach2( __ptr, num)                            \
            for (   uint_fast32_t SAFE_NAME(count) = num;    \
                    SAFE_NAME(count) > 0;                    \
                    __ptr++, SAFE_NAME(count)--              \
                )

/* 新建一个指针,名为：“_” ，从开始地址遍历num个值，不改变 _ptr的值 ，遍历打印使用指针： “_” */
#define ptr_foreach3(__type, __ptr, num)                     \
            using(__type *_ = __ptr, _ = _ , _ = _)                \
            for (   uint_fast32_t SAFE_NAME(count) = num;    \
                    SAFE_NAME(count) > 0;                    \
                    _++, SAFE_NAME(count)--                  \
                )

/* 最终宏 */
#define ptr_foreach(...)                                                            \
            CONNECT2(ptr_foreach, VA_ARGS_COUNT(__VA_ARGS__))(__VA_ARGS__)


/**
 * @brief 9、 求最大最小值
 * 
 */
#ifndef MIN
#   define MIN(__a, __b)  ((__a) <= (__b) ? (__a) : (__b))
#endif

#ifndef MAX
#   define MAX(__a, __b)  ((__a) >= (__b) ? (__a) : (__b))
#endif




/**
 * @brief 10、局部指针声明工具
 *          在with的{}内作用，避免重复的类型定义
 * method：
 *   两个参数，with(__type, __addr),    使用指针 _ 进行使用
 *   或   
 *   三个参数，with(__type, __addr, __item)，使用指针 __item ,不需要预先声明
 */

#undef __with2
#undef __with3
#undef with

#define __with2(__type, __addr)                                                 \
            using(__type *_=(__addr))

#define __with3(__type, __addr, __item)                                         \
            using(__type *_=(__addr), *__item = _, _=_,_=_ )

#define with(...)                                                               \
            CONNECT2(__with, VA_ARGS_COUNT(__VA_ARGS__))(__VA_ARGS__)




/**
 * @brief TODO：计算{}内函数的执行时间，在linux上用处不大。
 *      这个结构可以拿来做其他用处,这个宏中，相关变量为全局变量，故宏暂时不可用
 * 
 */
// #define __cycleof__(__STR, __get_system_ticks, ...)                                                         \
//             using(  int64_t _ = __get_system_ticks(),                                     \
//                     __cycle_count__ = _,                                                \
//                     _=_,                                                                \
//                     {                                                                   \
//                     _ = __get_system_ticks() - _ - g_nOffset;                             \
//                     __cycle_count__ = _;                                                \
//                         if (VA_ARGS_COUNT(__VA_ARGS__) == 0) {                          \
//                             printf("\r\n");                                             \
//                             printf("-[Cycle Report]");                                  \
//                             printf(                                                     \
//                                 "------------------------------------\r\n");            \
//                             printf(                                                     \
//                                 __STR " total cycle count: %ld [%08lx]\r\n",            \
//                                     (long)_, (long)_);                                  \
//                         }                                                               \
//                         else {                                                          \
//                             __VA_ARGS__                                                 \
//                         };                                                              \
//                     }                                                                   \
//                 )

#define __leave_of_everything_(__STR, ...)                                                         \
            using(  int64_t a = 4,                                     \
                    b  = 5,                                                \
                    a = a,                                                                \
                    {                                                                   \
                    a = 9;                             \
                    b = a;                                                \
                        if (VA_ARGS_COUNT(__VA_ARGS__) == 0) {                          \
                            printf("\r\n");                                             \
                            printf("-[Cycle Report]");                                  \
                            printf(                                                     \
                                "------------------------------------\r\n");            \
                            printf(                                                     \
                                __STR " total cycle count: %ld [%08lx]\r\n",            \
                                    (long)a, (long)a);                                  \
                        }                                                               \
                        else {                                                          \
                            __VA_ARGS__                                                 \
                        };                                                              \
                    }                                                                   \
                )






/**
 * @brief 递归宏，当前最大支持10层嵌套。用于递减 执行函数功能。
 * method:
 *      RECURSIVE_MACRO(macro_func, n) 
 *          macro_func: 使用时定义一个宏函数，填入。递归宏就会逐次调用该宏函数进行执行。
 *          n:递归次数，给出最大递归次数，当前最大支持10次递归。
 */



// 基础宏定义，用于递减递归次数,这里使用具体数字而不是运算，为了更好兼容不同需求

#define DEC(x) CONNECT_N(DEC_,x)
#define DEC_0 0
#define DEC_1 0
#define DEC_2 1
#define DEC_3 2
#define DEC_4 3
#define DEC_5 4
#define DEC_6 5
#define DEC_7 6
#define DEC_8 7
#define DEC_9 8
#define DEC_10 9


// 当递归计数为0时，终止递归展开并打印递归停止信息
#define RECURSION_STOP(n) printf("Recursion level: %d - stop\n", n)

// 递归展开：每一级宏都会输出当前的递归计数，并调用上一级宏
#define RECURSION_STEP_0(func, n) do { func(n);  } while(0)
#define RECURSION_STEP_1(func, n) do { func(n); RECURSION_STEP_0(func, DEC(n)); } while(0)
#define RECURSION_STEP_2(func, n) do { func(n); RECURSION_STEP_1(func, DEC(n)); } while(0)
#define RECURSION_STEP_3(func, n) do { func(n); RECURSION_STEP_2(func, DEC(n)); } while(0)
#define RECURSION_STEP_4(func, n) do { func(n); RECURSION_STEP_3(func, DEC(n)); } while(0)
#define RECURSION_STEP_5(func, n) do { func(n); RECURSION_STEP_4(func, DEC(n)); } while(0)
#define RECURSION_STEP_6(func, n) do { func(n); RECURSION_STEP_5(func, DEC(n)); } while(0)
#define RECURSION_STEP_7(func, n) do { func(n); RECURSION_STEP_6(func, DEC(n)); } while(0)
#define RECURSION_STEP_8(func, n) do { func(n); RECURSION_STEP_7(func, DEC(n)); } while(0)
#define RECURSION_STEP_9(func, n) do { func(n); RECURSION_STEP_8(func, DEC(n)); } while(0)
#define RECURSION_STEP_10(func, n) do{ func(n); RECURSION_STEP_9(func, DEC(n)); } while(0)

// 主递归宏，选择递归展开次数（n最多为10）在 递归到0也会执行一次 macro_func
#define __RECURSIVE_MACRO(macro_func, n) RECURSION_STEP_##n(macro_func, n)

#define RECURSIVE_MACRO(macro_func, macro_n)  __RECURSIVE_MACRO(macro_func, macro_n)




#endif